package handwriting.learning;

import java.util.Iterator;
import java.util.Set;

import handwriting.editor.Drawing;
import handwriting.editor.SampleData;
//import handwriting.neural.Perceptron;
import handwriting.neural.NeuralNet;

public class Identifier extends RecognizerAI{
	private SampleData s;
	NeuralNet n;
	static double[] labelL = {0.0, 1.0};
	static double[] labelH = {1.0, 0.0};
	//static double[] labelL = {1.0, 1.0};
//	static double[] labelD = {0.0, 1.0, 0.0, 0.0};
//	static double[] labelE = {0.0, 1.0, 0.0, 1.0};
//	static double[] labelF = {0.0, 1.0, 1.0, 0.0};
//	static double[] labelG = {0.0, 1.0, 1.0, 1.0};
	public Identifier(SampleData samples, int numhidden) {
		super(samples);
		s = samples;
		n = new NeuralNet(20, numhidden, 2);
		//create neural net
		// TODO Auto-generated constructor stub
	}

	@Override
	public String classify(Drawing d) {
//		System.out.println("classify line 31");
		double[] coded = encode(d);
		double[] rawResults = n.compute(coded);
		double highest = 0;
		int highestindex = 0;
		for(int i = 0; i < rawResults.length; i++){
			if (rawResults[i] > highest){
				highest = rawResults[i];
				highestindex = i;
			}
		}
		if(highestindex == 1) return "L";
		if(highestindex == 0) return "H";
//		int maxValue = 0;  
//		  for(int i=1;i < rawResults.length;i++){  
//		    if(rawResults[i] > rawResults[maxValue]){  
//		      maxValue = i;  
//		    }  
//		  }
//		System.out.println("rawresults debug");
//		System.out.println(rawResults[0] + " "+rawResults[1] + " "+rawResults[2] + " "+rawResults[3]);
//		for(int i = 0; i <4; i++){
//			if(rawResults[i]>.5)
//				rawResults[i] = 1.0;
//			if(rawResults[i]<.5)
//				rawResults[i] = 0.0;
//		}
		
	//	System.out.println(rawResults[0] + " "+rawResults[1] + " "+rawResults[2] + " "+rawResults[3]);
	
//		if(compare(rawResults, labelL))
//			return "L";
//		if(compare(rawResults,labelB))
//			return "B";
//		if(rawResults == labelC)
//			return "C";
//		System.out.println("not recognized");
		return "not recognized";
	}
	
	public boolean compare(double[] arr1, double[] arr2){
		if(arr1.length != arr2.length)
			return false;
		for(int i = 0; i < arr1.length; i++){
			if(arr1[i] != arr2[i])
				return false;
		}
		return true;
	}
	
	public double[] encode(Drawing d){
		//		System.out.println("encode debug");
		boolean[][] image = d.getImage();
		double[] encode = new double[d.getWidth()];
		double m = 0;
		for(int i = 0; i < image.length; i++){
			m = 1;
			for(int j = 0; j < image[i].length; j++){
				if(image[i][j])m += Math.pow(2, j);//we should also try using 1's and 0's in a double, as a double will hold 2^64 (20 digits, starting with a 1)
//				m *= 10;
//				if(image[i][j])m+=1;
				
			}
			encode[i] = m;
//			System.out.print(encode[i] + " ");
		}
//		System.out.println("");
		return encode;
	}

//	public int trainUntil(double d, int i){//
//		return 0;
//	}

	@Override
	public void trainOnce(double learningRate) {
		Set<String> labelSet = s.allLabels();
		Iterator<String> it = labelSet.iterator();
		while (it.hasNext()) {
			String itLabel = (String) it.next();
			int numdraws = s.numDrawingsFor(itLabel);
			for(int j = 0; j< numdraws; j++){
				if(itLabel == "L")
					n.train(encode(s.getDrawing(itLabel, j)),labelL, learningRate);
				if(itLabel == "H")
					n.train(encode(s.getDrawing(itLabel, j)),labelH, learningRate);
		//		if(itLabel == "L")
		//			n.train(encode(s.getDrawing(itLabel, j)),labelL, learningRate);
			}
			
		}
		n.updateWeights();
//		System.out.println("DEBUg 2");
	}
}